package cn.buk.api.eotms.service;

import cn.buk.api.eotms.dto.*;
import cn.buk.common.dto.CommonDto;
import cn.buk.common.util.HttpUtil;
import cn.buk.common.util.JsonUtil;
import cn.buk.tms.common.dto.base.BaseDto;
import cn.buk.tms.common.dto.flight.BaseChangeOrderDto;
import cn.buk.tms.common.dto.flight.BaseRefundOrderDto;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import org.apache.hc.core5.http.NameValuePair;
import org.apache.hc.core5.http.message.BasicNameValuePair;

import java.util.ArrayList;
import java.util.List;

import static cn.buk.api.eotms.util.JsonUtil.createObjectMapper;

/**
 * @author yfdai
 */
public class FlightApiServiceImpl implements FlightApiService {

  /**
   * 应用id
   */
  private final String appId;

  /**
   * 应用密钥
   */
  private final String appSecret;

  /**
   * 接口地址
   */
  private final String url;

  /**
   * 用户名
   */
  private String username;

  /**
   * 密码
   */
  private String password;

  private boolean debugMode;

  public FlightApiServiceImpl(String appId, String appSecret, String url) {
    this.appId = appId;
    this.appSecret = appSecret;
    this.url = url;
  }

  public void setDebugMode(boolean debugMode) {
    this.debugMode = debugMode;
  }


  @Override
  public TokenResponse getToken() {
    var rq = new TokenRequest();
    rq.setAppId(this.appId);
    rq.setAppSecret(this.appSecret);

    List<NameValuePair> params = new ArrayList<>();
    params.add(new BasicNameValuePair("grant_type", rq.getGrantType()));
    params.add(new BasicNameValuePair("appid", rq.getAppId()));
    params.add(new BasicNameValuePair("secret", rq.getAppSecret()));

    String jsonStr = HttpUtil.postUrl(this.url + "/eotms/token", params);

    if (debugMode) {
      System.out.println(jsonStr);
    }

    return JsonUtil.convertJson2Obj(jsonStr, TokenResponse.class);
  }

  @Override
  public cn.buk.api.eotms.dto.LoginResponse login(LoginRequest rq) {
    List<NameValuePair> params = new ArrayList<>();
    if (rq == null) {
      params.add(new BasicNameValuePair("username", this.username));
      params.add(new BasicNameValuePair("password", this.password));
    } else {
      params.add(new BasicNameValuePair("username", rq.getUsername()));
      params.add(new BasicNameValuePair("password", rq.getPassword()));
    }

    String jsonStr = HttpUtil.postUrl(this.url + "/eotms/login", params);
    if (debugMode) {
      System.out.println(jsonStr);
    }
    return JsonUtil.convertJson2Obj(jsonStr, LoginResponse.class);
  }

  @Override
  public LoginResponse login() {
    return login(null);
  }

  @Override
  public LoginResponse checkLoginStatus(String token) {
    List<NameValuePair> params = new ArrayList<>();
    params.add(new BasicNameValuePair("token", token));

    String jsonStr = HttpUtil.getUrl(this.url + "/eotms/loginStatus", params);
    if (debugMode) {
      System.out.println(jsonStr);
    }
    return JsonUtil.convertJson2Obj(jsonStr, LoginResponse.class);
  }

  @Override
  public String[] getUserRoles(String token) {
    List<NameValuePair> params = new ArrayList<>();
    params.add(new BasicNameValuePair("token", token));

    String jsonStr = HttpUtil.getUrl(this.url + "/eotms/roles", params);
    if (debugMode) {
      System.out.println(jsonStr);
    }
    return JsonUtil.convertJson2Obj(jsonStr, String[].class);
  }

  @Override
  public UserProfile getUserProfile(String token) {
    List<NameValuePair> params = new ArrayList<>();
    params.add(new BasicNameValuePair("token", token));

    String jsonStr = HttpUtil.getUrl(this.url + "/eotms/profile", params);
    if (debugMode) {
      System.out.println(jsonStr);
    }
    return JsonUtil.convertJson2Obj(jsonStr, UserProfile.class);
  }

  @Override
  public PassengersResponse searchPassengers(String token, String name, int pageNo, int pageSize) {
    List<NameValuePair> params = new ArrayList<>();
    params.add(new BasicNameValuePair("token", token));
    params.add(new BasicNameValuePair("name", name));
    params.add(new BasicNameValuePair("pageNo", pageNo + ""));
    params.add(new BasicNameValuePair("pageSize", pageSize + ""));

    String jsonStr = HttpUtil.getUrl(this.url + "/eotms/passengers", params);
    if (debugMode) {
      System.out.println(jsonStr);
    }
    return JsonUtil.convertJson2Obj(jsonStr, PassengersResponse.class);
  }

  @Override
  public InsuranceResponse searchInsurances(String token, int pageNo, int pageSize) {
    List<NameValuePair> params = new ArrayList<>();
    params.add(new BasicNameValuePair("token", token));
    params.add(new BasicNameValuePair("pageNo", pageNo + ""));
    params.add(new BasicNameValuePair("pageSize", pageSize + ""));

    String jsonStr = HttpUtil.getUrl(this.url + "/eotms/vas/insurances", params);
    if (debugMode) {
      System.out.println(jsonStr);
    }
    return JsonUtil.convertJson2Obj(jsonStr, InsuranceResponse.class);
  }

  @Override
  public FlightOrderCreateResponse createFlightOrder(String token, FlightOrderCreateRequest rq) {
    List<NameValuePair> params = new ArrayList<>();
    params.add(new BasicNameValuePair("token", token));

    if (debugMode) {
      System.out.println(JsonUtil.toJSONString(rq));
    }

    String jsonStr = HttpUtil.postUrl(this.url + "/eotms/flight/order?token=" + token, JsonUtil.toJSONString(rq), true);
    if (debugMode) {
      System.out.println(jsonStr);
    }
    return JsonUtil.convertJson2Obj(jsonStr, FlightOrderCreateResponse.class);
  }

  @Override
  public CommonDto<FlightOrderResponse> searchFlightOrders(String token, String name, int pageNo, int pageSize) throws JsonProcessingException {
    List<NameValuePair> params = new ArrayList<>();
    params.add(new BasicNameValuePair("token", token));
    params.add(new BasicNameValuePair("sc.name", name));
    params.add(new BasicNameValuePair("sc.pageNo", pageNo + ""));
    params.add(new BasicNameValuePair("sc.pageSize", pageSize + ""));

    String jsonStr = HttpUtil.getUrl(this.url + "/eotms/flight/orders", params);
    if (debugMode) {
      System.out.println(jsonStr);
    }

    var mapper = createObjectMapper();
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    var javaType = mapper.getTypeFactory().constructParametricType(CommonDto.class, FlightOrderResponse.class);
    return  mapper.readValue(jsonStr, javaType);
  }

  @Override
  public FlightOrderResponse getFlightOrder(String token, int orderId) {
    List<NameValuePair> params = new ArrayList<>();
    params.add(new BasicNameValuePair("token", token));

    String jsonStr = HttpUtil.getUrl(this.url + "/eotms/flight/order/" + orderId, params);
    if (debugMode) {
      System.out.println(jsonStr);
    }
    return JsonUtil.convertJson2Obj(jsonStr, FlightOrderResponse.class);
  }

  @Override
  public FlightOrderResponse getFlightOrder(String token, String orderNo) {
    List<NameValuePair> params = new ArrayList<>();
    params.add(new BasicNameValuePair("token", token));

    String jsonStr = HttpUtil.getUrl(this.url + "/eotms/flight/order/orderNo/" + orderNo, params);
    if (debugMode) {
      System.out.println(jsonStr);
    }
    return JsonUtil.convertJson2Obj(jsonStr, FlightOrderResponse.class);
  }

  @Override
  public BaseDto submitFlightOrder(String token, int orderId) {
    List<NameValuePair> params = new ArrayList<>();
    params.add(new BasicNameValuePair("token", token));

    String jsonStr = HttpUtil.postUrl(this.url + "/eotms/flight/order/" + orderId + "/ticketing", params);
    if (debugMode) {
      System.out.println(jsonStr);
    }
    return JsonUtil.convertJson2Obj(jsonStr, BaseDto.class);
  }

  @Override
  public CommonDto<BaseRefundOrderDto> searchFlightRefundOrders(String token, String psgName, int pageNo, int pageSize) throws JsonProcessingException {
    List<NameValuePair> params = new ArrayList<>();
    params.add(new BasicNameValuePair("token", token));
    params.add(new BasicNameValuePair("sc.name", psgName));
    params.add(new BasicNameValuePair("sc.pageNo", pageNo + ""));
    params.add(new BasicNameValuePair("sc.pageSize", pageSize + ""));

    String jsonStr = HttpUtil.getUrl(this.url + "/eotms/flight/refunds", params);
    if (debugMode) {
      System.out.println(jsonStr);
    }
    return JsonUtil.convertJson2Obj(jsonStr, CommonDto.class, BaseRefundOrderDto.class, true);
  }

  @Override
  public BaseRefundOrderDto getFlightRefundOrder(String token, int orderId) {
    List<NameValuePair> params = new ArrayList<>();
    params.add(new BasicNameValuePair("token", token));

    String jsonStr = HttpUtil.getUrl(this.url + "/eotms/flight/refund/" + orderId, params);
    if (debugMode) {
      System.out.println(jsonStr);
    }
    return JsonUtil.convertJson2Obj(jsonStr, BaseRefundOrderDto.class);
  }

  @Override
  public BaseDto createFlightRefundOrder(String token, RefundOrderCreateRequest rq) {
    List<NameValuePair> params = new ArrayList<>();
    params.add(new BasicNameValuePair("token", token));

    if (debugMode) {
      System.out.println("request: " + JsonUtil.toJSONString(rq));
    }

    String jsonStr = HttpUtil.postUrl(this.url + "/eotms/flight/refund?token=" + token, JsonUtil.toJSONString(rq), true);

    if (debugMode) {
      System.out.println("response: " + jsonStr);
    }
    return JsonUtil.convertJson2Obj(jsonStr, BaseDto.class);
  }

  @Override
  public CommonDto<BaseChangeOrderDto> searchFlightChangeOrders(String token, String psgName, int pageNo, int pageSize) throws JsonProcessingException {
    List<NameValuePair> params = new ArrayList<>();
    params.add(new BasicNameValuePair("token", token));
    params.add(new BasicNameValuePair("sc.name", psgName));
    params.add(new BasicNameValuePair("sc.pageNo", pageNo + ""));
    params.add(new BasicNameValuePair("sc.pageSize", pageSize + ""));

    String jsonStr = HttpUtil.getUrl(this.url + "/eotms/flight/changes", params);
    if (debugMode) {
      System.out.println(jsonStr);
    }
    var mapper = createObjectMapper();
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    var javaType = mapper.getTypeFactory().constructParametricType(CommonDto.class, BaseChangeOrderDto.class);
    return  mapper.readValue(jsonStr, javaType);
  }

  @Override
  public BaseChangeOrderDto getFlightChangeOrder(String token, int orderId) {
    List<NameValuePair> params = new ArrayList<>();
    params.add(new BasicNameValuePair("token", token));

    String jsonStr = HttpUtil.getUrl(this.url + "/eotms/flight/change/" + orderId, params);
    if (debugMode) {
      System.out.println(jsonStr);
    }
    return JsonUtil.convertJson2Obj(jsonStr, BaseChangeOrderDto.class);
  }

  @Override
  public BaseDto createFlightChangeOrder(String token, ChangeOrderCreateRequest rq) {
    List<NameValuePair> params = new ArrayList<>();
    params.add(new BasicNameValuePair("token", token));

    if (debugMode) {
      System.out.println("request: " + JsonUtil.toJSONString(rq));
    }

    String jsonStr = HttpUtil.postUrl(this.url + "/eotms/flight/change?token=" + token, JsonUtil.toJSONString(rq), true);

    if (debugMode) {
      System.out.println("response: " + jsonStr);
    }
    return JsonUtil.convertJson2Obj(jsonStr, BaseDto.class);
  }

  public String getUsername() {
    return username;
  }

  public void setUsername(String username) {
    this.username = username;
  }

  public String getPassword() {
    return password;
  }

  public void setPassword(String password) {
    this.password = password;
  }
}
